package org.example.blockingQueue;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * 阻塞队列：
 * 相较于Queue多了两个特性
 * 1. 队列满时，生产者线程会等待队列可用
 * 2. 队列空时，消费者线程会等待队列非空
 */
public class ArrayBlockingQueueDemo {

    public static void main(String[] args) {
        // 创建容量大小为3的阻塞队列
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);

        // doException(blockingQueue);
        // doReturn(blockingQueue);
        // doBlock(blockingQueue);
        doWaitBlock(blockingQueue);
    }

    // 抛出异常式
    private static void doException(BlockingQueue<String> blockingQueue) {
        // 添加
        System.out.println(blockingQueue.add("1"));
        System.out.println(blockingQueue.add("2"));
        System.out.println(blockingQueue.add("3"));
        // System.out.println(blockingQueue.add("4")); // java.lang.IllegalStateException: Queue full

        // 队首
        System.out.println("队首：" + blockingQueue.element());

        // 移除
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        // System.out.println(blockingQueue.remove()); // java.util.NoSuchElementException
    }

    // 有返回值，不抛出异常式
    private static void doReturn(BlockingQueue<String> blockingQueue) {
        // 添加
        System.out.println(blockingQueue.offer("1"));
        System.out.println(blockingQueue.offer("2"));
        System.out.println(blockingQueue.offer("3"));
        System.out.println(blockingQueue.offer("4"));

        // 队首
        System.out.println("队首：" + blockingQueue.peek());

        // 移除
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
    }

    // 阻塞式
    private static void doBlock(BlockingQueue<String> blockingQueue) {
        try {
            // 添加
            blockingQueue.put("1");
            blockingQueue.put("2");
            blockingQueue.put("3");
            // blockingQueue.put("4"); // 无限阻塞

            // 移除
            System.out.println(blockingQueue.take());
            System.out.println(blockingQueue.take());
            System.out.println(blockingQueue.take());
            // System.out.println(blockingQueue.take()); // 无限阻塞
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    // 超时等待式
    private static void doWaitBlock(BlockingQueue<String> blockingQueue) {
        // 添加
        System.out.println(blockingQueue.offer("1"));
        System.out.println(blockingQueue.offer("2"));
        System.out.println(blockingQueue.offer("3"));
        try {
            System.out.println(blockingQueue.offer("4", 3, TimeUnit.SECONDS)); // 超时等待
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 移除
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        try {
            System.out.println(blockingQueue.poll(2, TimeUnit.SECONDS));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
